﻿using System;
using System.Collections.Generic;
using System.Linq;
using WeiBeeCommon.Core;
using WeiBeeCommon.DataTypes;
using System.IO;
using System.Xml.Serialization;

namespace WeiBeeCommon.Helpers
{
    public class BatchComment
    {
        List<WeiBeeSina> sinas = new List<WeiBeeSina>();
        private SearchHelper searchHelper = new SearchHelper();

        /// <summary>
        /// Initialize with a WeiBee object
        /// </summary>
        /// <param name="weibee">The WeiBee object use for comment</param>
        public BatchComment(WeiBeeSina weibee)
        {
            AddOneWeiBee(weibee);
            _currentWeiBee = 0;
        }

        /// <summary>
        /// Add one WeiBee object, so that BatchComment can have more effience
        /// </summary>
        /// <param name="weibee">The WeiBee object use for more comment</param>
        public void AddOneWeiBee(WeiBeeSina weibee)
        {
            sinas.Add(weibee);
            SetQueueSizeLimit();
        }

        private void SetQueueSizeLimit()
        {
            _queuesizelimit = sinas.Count*3;
        }

        /// <summary>
        /// Comment a qualified twitter with defined sentence
        /// </summary>
        /// <returns></returns>
        public string Comment(string ad = null)
        {
            _currentWeiBee = (_currentWeiBee + 1) % sinas.Count;

            var s = GetNextCommentStatus();

            if( s == null )
            {
                return "Error";
            }

            string comment = string.Format("{0} - {1}",WeiBeeCommentGenerator.OrderedComment(), string.IsNullOrEmpty(ad)?"":ad);
            comment = comment.Length > 140 ? comment.Substring(0,140) : comment;
            return sinas[_currentWeiBee].Comment(s.id, comment);
        }

        private int _queuesizelimit = 1;
        private SinaStatus GetNextCommentStatus()
        {
            List<SinaStatus> statusList;
            var currentTime = DateTime.Now;
            if (currentTime.Subtract(_lastgetpublic).TotalSeconds >= 60)
            {
                statusList = sinas[_currentWeiBee].GetPublicTimelines(100);
                statusList = FilterOutByCritria(statusList);

                foreach (var status in statusList.FindAll(st => searchHelper.IsStatusQualified(st)))
                {
                    _visitQueue.Enqueue(status);
                }
                while (_visitQueue.Count >= _queuesizelimit)
                {
                    _visitQueue.Dequeue();
                }
                _oldstatus = statusList;
                _lastgetpublic = currentTime;
            }
            else
            {
                statusList = _oldstatus;
                statusList.Remove(_lastCommented);
            }

            // Not a MUST to comment, should increase Keywords for comment
            var s = _visitQueue.Count > 0 ? _visitQueue.Dequeue() : null;// : statusList.First();

            if (s != null)
            {
                _lastCommented = s;
                _visitedHelper.AppendToVisited(s.user.id);
            }
            return s;
        }
        private SinaStatus _lastCommented;
        private List<SinaStatus> _oldstatus;
        private DateTime _lastgetpublic = new DateTime(2011,1,1);

        public List<SinaStatus> FilterOutByCritria(List<SinaStatus> statusList)
        {
            if( statusList==null || statusList.Count==0 )
            {
                return null;
            }
            var counts = sinas[_currentWeiBee].GetCounts(statusList);
            if (counts.Count==0)
            {
                return statusList.Where(sinaStatuse => !_visitedHelper.VisitedUserIdList.Contains(sinaStatuse.user.id) && string.IsNullOrEmpty(sinaStatuse.in_reply_to_user_id)).ToList();
            }
            return statusList.Where(sinaStatuse => counts.Any(cc => (cc.id == sinaStatuse.id) && (cc.comments == 0)) && !_visitedHelper.VisitedUserIdList.Contains(sinaStatuse.user.id) && string.IsNullOrEmpty(sinaStatuse.in_reply_to_user_id)).ToList(); ;
        }

        private int _currentWeiBee;
        private readonly Queue<SinaStatus> _visitQueue = new Queue<SinaStatus>();

        private const string CommentFile = "comment.xml";
        private CommentGenerator _comment;
        private CommentGenerator WeiBeeCommentGenerator
        {
            get
            {
                if (_comment == null)
                {
                    if (File.Exists(CommentFile))
                    {
                        using (var fs = new FileStream(CommentFile, FileMode.Open, FileAccess.Read))
                        {
                            var xml = new XmlSerializer(typeof(CommentGenerator));
                            _comment = xml.Deserialize(fs) as CommentGenerator;
                        }
                    }
                    if (_comment == null)
                    {
                        InitCommentWithDefaultValue();
                    }
                }
                return _comment;
            }
        }

        private void InitCommentWithDefaultValue()
        {
            _comment = new CommentGenerator();
            _comment.Emote = new List<string> { "嗯", "哦", "顶", "支持", "赞", "哈" };
            _comment.Sofa = new List<string> { "沙发", "抢沙发", "sofa", "你好", "沙发沙发", " " };
            _comment.Invite = new List<string> { "也来偶滴微博看看", "粉粉更健康", "我的微博欢迎你", "粉粉", "你是我的偶像", "我是你的滴粉", " " };
            _comment.Splitter = new List<string> { "~", "。。。", "...", "~~", "," };
            using (var fs = new FileStream(CommentFile, FileMode.Create, FileAccess.Write))
            {
                var xml = new XmlSerializer(typeof(CommentGenerator));
                xml.Serialize(fs, _comment);
            }
        }
        #region Visited
        VisitedHelper _visitedHelper = new VisitedHelper("sinavisited.xml");
        #endregion
    }
}
